package com.lyfei.yd.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lyfei.yd.common.exception.CustomException;
import com.lyfei.yd.system.domain.dto.SpuDTO;
import com.lyfei.yd.system.domain.dto.SpuPageQueryDto;
import com.lyfei.yd.system.domain.entity.*;
import com.lyfei.yd.system.domain.vo.SpuVo;
import com.lyfei.yd.system.mapper.SpuMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service("spuService")
public class SpuService extends BaseService<SpuMapper, Spu> {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuImgService spuImgService;

    @Autowired
    private SpecKeyService specKeyService;

    @Autowired
    private SpuSpecKeyService spuSpecKeyService;

    @Autowired
    private SpuAttributeService spuAttributeService;

    @Autowired
    private SkuService skuService;

    @Transactional
    public void create(SpuDTO dto) {
        Spu spu = new Spu();
        BeanUtils.copyProperties(dto, spu);
        spu.setCreateTime(new Date());
        spu.setUpdateTime(new Date());
        Category category = categoryService.getById(dto.getCategoryId());
        spu.setRootCategoryId(category.getParentId());
        this.save(spu);

        List<String> spuImgList = new ArrayList<>();
        if (dto.getSpuImgList() == null || dto.getSpuImgList().isEmpty()) {
            spuImgList.add(dto.getImg());
        }else {
            spuImgList = java.util.Arrays.asList(dto.getSpuImgList().split(","));
        }
        this.insertSpuImgList(spu.getId(), spuImgList);

        if(dto.getSpecKeyIdList()!=null && !dto.getSpecKeyIdList().isEmpty()) {
            this.insertSpuKeyList(spu.getId(), dto.getSpecKeyIdList());
        }

        if(dto.getAttributes()!=null && !dto.getAttributes().isEmpty()) {
            this.insertSpuAttributeList(spu.getId(), dto.getAttributes());
        }
    }

    public void update(SpuDTO dto, Long id) {
        Spu spu = this.getById(id);
        if(spu==null) {
            throw new CustomException("商品不存在");
        }

        BeanUtils.copyProperties(dto, spu);
        spu.setUpdateTime(new Date());
        Category category = categoryService.getById(dto.getCategoryId());
        if(category.getParentId() != null) {
            spu.setRootCategoryId(category.getParentId());
        }
        this.updateById(spu);
        List<String> spuImgList = new ArrayList<>();
        if (dto.getSpuImgList() == null || dto.getSpuImgList().isEmpty()) {
            spuImgList.add(dto.getImg());
        }else {
            spuImgList = java.util.Arrays.asList(dto.getSpuImgList().split(","));
        }
        spuImgService.hardDeleteBySpuId(spu.getId());
        this.insertSpuImgList(spu.getId(), spuImgList);

        this.updateSpuKey(spu.getId(), dto.getSpecKeyIdList());
    }


    public void delete(Long id) {
        Spu spu = this.getById(id);
        if(spu==null) {
            throw new CustomException("商品不存在");
        }

        this.removeById(id);
    }

    public IPage<SpuVo> page(SpuPageQueryDto dto) {
        IPage<Spu> spuPage = this.page(new Page<>(dto.getCurrent(), dto.getPageSize()), new LambdaQueryWrapper<Spu>()
               .like(StringUtils.hasText(dto.getTitle()), Spu::getTitle, dto.getTitle()).orderByDesc(Spu::getUpdateTime));

        IPage<SpuVo> spuVoPage = new Page<>();
        spuVoPage.setCurrent(spuPage.getCurrent());
        spuVoPage.setSize(spuPage.getSize());
        spuVoPage.setTotal(spuPage.getTotal());
        spuVoPage.setRecords(spuPage.getRecords().stream().map(spu -> {
            SpuVo spuVo = new SpuVo();
            BeanUtils.copyProperties(spu, spuVo);
            Category category = categoryService.getById(spu.getCategoryId());
            spuVo.setCategoryName(category.getName());
            Category rootCategory = categoryService.getById(spu.getRootCategoryId());
            spuVo.setRootCategoryName(rootCategory.getName());
            return spuVo;
        }).collect(Collectors.toList()));
        return spuVoPage;
    }

    public IPage<Spu> getByCategoryId(Long categoryId, Integer current, Integer size) {
        Page<Spu> spuPage = new Page<>(current, size);
        return this.page(spuPage, new LambdaQueryWrapper<Spu>().eq(Spu::getCategoryId, categoryId)
                .eq(Spu::getDeleted, false));
    }

    public SpuVo detail(Long id) {
        Spu spu = this.getById(id);
        if(spu == null) {
            throw new CustomException("商品不存在");
        }

        SpuVo spuVo = new SpuVo();
        BeanUtils.copyProperties(spu, spuVo);

        if(spu.getCategoryId() != null) {
            Category category = categoryService.getById(spu.getCategoryId());
            spuVo.setCategoryName(category.getName());
        }

        if(spu.getSketchSpecId() != null) {
            SpecKey specKey = specKeyService.getById(spu.getSketchSpecId());
            spuVo.setSketchSpecName(specKey.getName());
        }

        // 查询sku信息
        QueryWrapper<Sku> skuQueryWrapper = new QueryWrapper<>();
        skuQueryWrapper.eq("spu_id", spu.getId());
        List<Sku> skuList = skuService.list(skuQueryWrapper);
        spuVo.setSkuList(skuList);

        QueryWrapper<SpuImg> spuImgQueryWrapper = new QueryWrapper<>();
        spuImgQueryWrapper.eq("spu_id", spu.getId());
        List<SpuImg> spuImgList = spuImgService.list(spuImgQueryWrapper);
        spuVo.setSpuImgList(spuImgList);

        QueryWrapper<SpuAttribute> spuAttributeQueryWrapper = new QueryWrapper<>();
        spuAttributeQueryWrapper.eq("spu_id", spu.getId());
        List<SpuAttribute> spuAttributeList = spuAttributeService.list(spuAttributeQueryWrapper);
        spuVo.setSpuAttributes(spuAttributeList);

        return spuVo;
    }

    public List<Long> getSpecKeys(Long spuId) {
        List<SpuSpecKey> spuSpecKeys = spuSpecKeyService.list(new LambdaQueryWrapper<SpuSpecKey>()
                .eq(SpuSpecKey::getSpuId, spuId));

        return spuSpecKeys.stream()
                .map(SpuSpecKey::getSpecKeyId)
                .collect(Collectors.toList());
    }

    private void insertSpuImgList(Long spuId, List<String> imgList) {
        List<SpuImg> spuImgList = imgList.stream()
                .map(img -> {
                    SpuImg spuImg = new SpuImg();
                    spuImg.setSpuId(spuId);
                    spuImg.setImg(img);
                    return spuImg;
                })
                .collect(Collectors.toList());

        this.spuImgService.saveBatch(spuImgList);
    }

    private void insertSpuKeyList(Long spuId, List<Long> specKeyIdList) {
        List<SpuSpecKey> spuSpecKeys = specKeyIdList.stream()
                .map(sk -> {
                    SpuSpecKey specKey = new SpuSpecKey();
                    specKey.setSpuId(spuId);
                    specKey.setSpecKeyId(sk);
                    return specKey;
                })
                .collect(Collectors.toList());

        this.spuSpecKeyService.saveBatch(spuSpecKeys);
    }

    private void insertSpuAttributeList(Long id, List<SpuAttribute> attributes) {
        attributes.forEach(a -> a.setSpuId(id));
        spuAttributeService.saveBatch(attributes);
    }

    private void updateSpuKey(Long spuId, List<Long> specKeyIdList) {

        QueryWrapper<SpuSpecKey> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("spu_id", spuId);
        spuSpecKeyService.remove(queryWrapper);

        if(specKeyIdList != null && !specKeyIdList.isEmpty()) {

            List<SpuSpecKey> spuSpecKeys = specKeyIdList.stream()
                    .map(sk -> {
                        SpuSpecKey specKey = new SpuSpecKey();
                        specKey.setSpuId(spuId);
                        specKey.setSpecKeyId(sk);
                        return specKey;
                    })
                    .collect(Collectors.toList());

            spuSpecKeyService.saveBatch(spuSpecKeys);
        }
    }
}
